package com.cancer.controller.user;

import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cancer.application.BaseServlet;
import com.cancer.biz.auth.entity.User;
import com.cancer.biz.auth.service.UserService;
import com.cancer.biz.auth.service.WechatService;
import com.cancer.biz.common.SysConfigUtils;
import com.cancer.biz.common.exception.DataException;
import com.cancer.common.FfUtil;
import com.cancer.common.util.CollectionUtil;
import com.cancer.common.util.Lang;
import com.cancer.common.util.MD5Utils;
import com.cancer.common.util.WeixinUtil;
import com.cancer.common.web.APIModel;
import com.cancer.common.web.PageBean;

import io.vertx.core.Vertx;
import io.vertx.core.eventbus.DeliveryOptions;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.json.JsonObject;

/**
 * @Company GeekPlus
 * @TypeName UserController
 * @Description 用户相关的Controller
 * @Project beetle
 * @since 1.0.0
 * @Author bai
 * @Date 2018年1月17日 下午5:12:43
 */
@Controller
@RequestMapping("/api_v1/user")
public class UserController {
	private Vertx vertx;
	//公用超时时间设置为6秒
    DeliveryOptions dop = new DeliveryOptions().setSendTimeout(6000L);
	private final static Logger logger = LoggerFactory.getLogger(UserController.class);
	@Autowired
	private UserService userService;
	@Autowired
	private WechatService wechatService;
	
	/**
	 * 校验微信服务
	 * @return
	 */
	@RequestMapping(value = "/checkWeixinUser", method = {RequestMethod.GET })
	@ResponseBody
	public Object checkWeixinUser(String signature,String timestamp,String nonce,String echostr) {
		logger.info("signature:{}",signature);
		logger.info("timestamp:{}",timestamp);
		logger.info("nonce:{}",nonce);
		logger.info("echostr:{}",echostr);
		String currentToken=WeixinUtil.getCurrentToken();
		String currentTicket=WeixinUtil.getJsapiTicket();
		logger.info("token:"+currentToken+"&currentTicket="+currentTicket);
		String token=SysConfigUtils.getValue("token");
		if(WeixinUtil.checkSignature(signature,timestamp,nonce,token)){
			return echostr;
		}
		return null;
	}
	
	/**
     * 校验微信服务
     * @return
     */
    @RequestMapping(value = "/checkWeixinUser", method = {RequestMethod.POST })
    @ResponseBody
    public String even(HttpServletRequest request,HttpServletResponse response) {
    	String res = wechatService.processRequest(request);
    	return res;
    }
    
    @RequestMapping(value = "/getticket", method = { RequestMethod.POST })
    @ResponseBody
    public Object getticket(String url) {
        Map<String,Object> map=new HashMap<String,Object>();
         String timestamp = String.valueOf(System.currentTimeMillis());
         String noncestr = FfUtil.getMD5Hash16(timestamp);
         String jsapi_ticket=WeixinUtil.getJsapiTicket();
         String appId=SysConfigUtils.getValue("appId");
         String signature = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
         map.put("appId", appId);
         map.put("noncestr", noncestr);
         map.put("timestamp", timestamp);
         map.put("signature", FfUtil.getSHA1(signature));
         APIModel model = new APIModel();
        model.set(0,"success", map);
        logger.info("noncestr:"+noncestr);
        logger.info("timestamp:"+timestamp);
        logger.info("signature:"+map.get("signature").toString());
         return map;
    }
	
	/**
	 * @Company GeekPlus
	 * @Description 去登录的页面
	 * @return
	 * @Author guojianxia
	 * @Date 2016年1月8日 上午9:24:38
	 */
	@RequestMapping(value = "/toLoginPage", method = { RequestMethod.GET,RequestMethod.POST })
	@ResponseBody
	public Object toLoginPage() {
		APIModel model = new APIModel();
		model.set(2, "toLogin", null);
		return model;
	}

	/**
	 * 返回没有权限
	 *
	 * @author guojianxia 2016年11月29日
	 * @return
	 */
	@RequestMapping(value = "/toUnauthorized", method = { RequestMethod.GET })
	@ResponseBody
	public Object toUnauthorized() {
		//return "user/unauthorizedUrl";
		APIModel model = new APIModel();
		/*model.set(3, "toUnauthorizedPage", null);*/
		model.set(3,Lang.msg("web.c.UserAPI.item0097"), null);
		return model;
	}

	/**
	 * 获取当前登录用户API
	 *
	 * @author guojianxia 2017年1月5日
	 * @return
	 */
	@RequestMapping(value = "/getCurrentUser", method = { RequestMethod.GET })
	@ResponseBody
	public Object getCurrentUser() {
		APIModel model = new APIModel();
		try {
			Subject subject = SecurityUtils.getSubject();
			User user = (User) subject.getPrincipal();
			if (null != user) {
				model.set(0, "success", user);
			} else {
				model.set(1,Lang.msg("web.c.UserAPI.item0098"), null);
			}
		} catch (Exception e) {
			model.set(1,Lang.msg("web.c.UserAPI.item0099"), null);
			logger.error("获取当前用户时发生异常，异常信息：{}", e.toString());
		}
		return model;
	}

	/**
	 * @Company GeekPlus
	 * @Description 用户登录的方法
	 * @param request
	 * @param username
	 * @param password
	 * @return
	 * @Author guojianxia
	 * @Date 2016年1月7日 下午5:30:43
	 */
	@RequestMapping(value = "/login", method = { RequestMethod.POST })
	@ResponseBody
	public Object login(String username, String password) {
		APIModel model = new APIModel();
		// 用户名不能为空
		if (StringUtils.isNotBlank(username)) {
			// 密码不能为空
			if (StringUtils.isNotBlank(password)) {
				Subject subject = SecurityUtils.getSubject();
				AuthenticationToken authenticationToken = new UsernamePasswordToken(username, MD5Utils.md5(password));
				try {
					// shiro进行用户的认证
					subject.login(authenticationToken);
					// 将认证后的用户返回
					User user = (User) subject.getPrincipal();
					if (user.getStatus() == 1) {
						// 将查到了的用户放到session里
						Session session = subject.getSession();
						session.setAttribute("loginUser", user);
						logger.info("用户：{}登录了系统。", username);
						String sessionId = session.getId().toString();
						Map<String, String> data = new HashMap<String, String>();
						data.put("sessionId", sessionId);
						model.set(0, "success", data);
						return model;
					} else {
						// 将认证的用户踢掉
						subject.logout();
						model.set(1,Lang.msg("web.c.UserAPI.item0100"), null);
						return model;
					}
				} catch (UnknownAccountException e) {
					model.set(1,Lang.msg("web.c.UserAPI.item0101"), null);
					return model;
				} catch (AuthenticationException e) {
					// 用户名或密码错误
					model.set(1, Lang.msg("web.c.UserAPI.item0102"), null);
					return model;
				} catch (Exception e) {
					model.set(1, Lang.msg("web.c.UserAPI.item0099"), null);
					logger.error("用户登录发生异常，异常信息：{}", e.toString());
					return model;
				}
			} else {
				model.set(1, Lang.msg("web.c.UserAPI.item0103"), null);
				return model;
			}
		} else {
			model.set(1, Lang.msg("web.c.UserAPI.item0104"), null);
			return model;
		}
	}

	private String getCurrentSessionId() {
		String sessionID = "";
		Subject subject = SecurityUtils.getSubject();
		Session session = subject.getSession();
		sessionID = session.getId().toString();
		if (StringUtils.isEmpty(sessionID)) {
			return StringUtils.EMPTY;
		}
		return sessionID;
	}

	/**
	 * @Company GeekPlus
	 * @Description 用户退出系统
	 * @return
	 * @Author guojianxia
	 * @Date 2016年1月8日 上午10:12:18
	 */
	@RequestMapping(value = "/logout", method = { RequestMethod.GET })
	@ResponseBody
	public Object logout() {
		Subject subject = SecurityUtils.getSubject();
		// 将subject（当前用户）状态修改为“未认证”状态,同时它也销毁了session的
		APIModel model = new APIModel();
		try {
			logger.info("用户：{}退出了系统。", ((User) subject.getPrincipal()).getUsername());
			subject.logout();
			// 登出成功返回值
			model.set(0, "success", null);
		} catch (Exception e) {
			// 登出异常返回值
			model.set(1, Lang.msg("web.c.UserAPI.item0105"), null);
		}
		return model;
	}

	/**
	 * @Company GeekPlus
	 * @Description 查询所有用户，还要进行分页和多条件
	 * @param model
	 * @return
	 * @Author guojianxia
	 * @Date 2016年1月8日 下午6:44:41
	 */
	// @RequiresPermissions(value = "user")
	@RequestMapping(value = "/userList", method = { RequestMethod.GET })
	@ResponseBody
	public Object queryAllUser(Integer roleId, User user) {
		APIModel model = new APIModel();
		try {
			// 返回分页对象
			PageBean<User> pageBean = userService.queryAllUser(roleId, user);
			if (pageBean != null && pageBean.getPageSize() > 0) {
				// 有用户数据的返回值
				model.set(0, "success", pageBean);
			} else {
				// 没有用户数据的返回值
				model.set(1, Lang.msg("web.c.UserAPI.item0106"), pageBean);
			}
		} catch (Exception e) {
			model.set(1, Lang.msg("web.c.UserAPI.item0107"), null);
			logger.error("查询用户时发生异常", e.toString());
		}
		return model;
	}

	/**
	 * @Company GeekPlus
	 * @Description TODO 根据用户id查询用户的详细信息，包括所具有的权限
	 * @param userId
	 * @return
	 * @Author guojianxia
	 * @Date 2016年1月15日 下午6:15:55
	 */
	@RequestMapping(value = "/userDetail", method = { RequestMethod.GET })
	@ResponseBody
	public Object queryUserDetailById(Integer userId) {
		APIModel model = new APIModel();
		return model;
	}

	/**
	 * @Company GeekPlus
	 * @Description 验证用户输入的旧密码是否正确
	 * @param oldPassword 用户输入的旧密码
	 * @return
	 * @Author guojianxia
	 * @Date 2016年1月12日 上午11:35:40
	 */
	@RequestMapping(value = "/checkPassword", method = { RequestMethod.GET })
	@ResponseBody
	public Object checkPassword(String oldPassword) {
		APIModel model = new APIModel();
		try {
			// 取出当前用户
			Subject subject = SecurityUtils.getSubject();
			User user = (User) subject.getPrincipal();
			// 取出用户的密码
			String password = user.getPassword();
			if (password.equals(MD5Utils.md5(oldPassword))) {
				// 用户输入的旧密码与用户原来的密码相同
				model.set(0, "success", null);
			} else {
				// 用户输入的密码与原来密码不匹配
				model.set(1, Lang.msg("web.c.UserAPI.item0108"), null);
			}
		} catch (Exception e) {
			model.set(1, Lang.msg("web.c.UserAPI.item0109"), null);
			logger.error("比较用户密码发生异常，异常信息为：{}", e.toString());
		}
		return model;
	}

	/**
	 * @Company GeekPlus
	 * @Description 修改密码
	 * @param password
	 * @return
	 * @Author guojianxia
	 * @Date 2016年1月8日 下午6:45:42
	 */
	@RequestMapping(value = "/updatePassword", method = { RequestMethod.POST })
	@ResponseBody
	public Object updatePassword(String oldPassword, String password) {
		APIModel model = new APIModel();
		try {
			// 取出当前用户
			Subject subject = SecurityUtils.getSubject();
			User user = (User) subject.getPrincipal();
			// 取出用户的密码
			String userPassword = user.getPassword();
			if (userPassword.equals(MD5Utils.md5(oldPassword))) {
				// 设置用户的新密码
				user.setPassword(MD5Utils.md5(password));
				Boolean isSuccess = userService.updateUser(user);
				if (isSuccess) {
					// 密码修改成功后，将用户踢出，让其重新登录
					subject.logout();
					// 修改成功返回值
					model.set(0, "success", null);
				} else {
					model.set(1, Lang.msg("web.c.UserAPI.item0110"), null);
				}
			} else {
				// 用户输入的密码与原来密码不匹配
				model.set(1,Lang.msg("web.c.UserAPI.item0111"), null);
			}
		} catch (Exception e) {
			model.set(1, Lang.msg("web.c.UserAPI.item0112"), null);
			logger.error("修改用户密码发生异常,异常信息为：{}", e.toString());
		}
		return model;
	}

	/**
	 * @Company GeekPlus
	 * @Description 添加一个用户
	 * @param user
	 * @return
	 * @Author guojianxia
	 * @Date 2016年1月8日 下午6:47:17
	 */
	@RequestMapping(value = "/addUser", method = { RequestMethod.POST })
	@ResponseBody
	public Object addUser(User user, Integer[] roleIds) {
		APIModel model = new APIModel();
		try {
			// 将密码加密
			user.setPassword(MD5Utils.md5(user.getPassword()));
			// 调用业务接口进行添加
			Boolean isSuccess = userService.addUser(user, roleIds);
			// 判断是否添加成功
			if (isSuccess) {
				model.set(0, "success", null);
			} else {
				model.set(1,Lang.msg("web.c.UserAPI.item0113"), null);
			}
		} catch (Exception e) {
			model.set(1,Lang.msg("web.c.UserAPI.item0114"), null);
			logger.error("发生异常,异常信息为：{}", e.toString());
		}
		return model;
	}


	/**
	 * @Company GeekPlus
	 * @Description 根据用户id删除一个用户
	 * @param id 用户id
	 * @param status 用户状态
	 * @return
	 * @Author guojianxia
	 * @Date 2016年1月8日 下午6:49:04
	 */
	@RequestMapping(value = "/disableUser", method = { RequestMethod.POST })
	@ResponseBody
	public Object disableUser(Integer id, Integer status) {
		APIModel model = new APIModel();
		String disable = "";
		switch (status) {
			case 0:
			disable = "禁用";
				break;
			case 1:
			disable = "启用";
				break;
			default:
				break;
		}
		try {
			if (id != null) {
				Boolean isSuccess = userService.updateUserStatus(id, status);
				if (isSuccess) {
					model.set(0, "success", null);
				} else {
					model.set(1, Lang.msg("web.c.UserAPI.item0123"), null);
				}
				return model;
			} else {
				model.set(1, Lang.msg("web.c.UserAPI.item0124"), null);
			}
		} catch (DataException e) {
			model.set(1, e.getMessage(), null);
			logger.error("修改用户发生异常,异常信息为：{}", e.toString());
		} catch (Exception e) {
			model.set(1, Lang.msg("web.c.UserAPI.item0125", disable), null);
			logger.error(disable + "用户发生异常,异常信息为：{}", e.toString());
		}
		return model;
	}

	/**
	 * 查询所有用户集合
	 * @author liudezhu 2017年9月4日
	 * @param user
	 * @return
	 */
	@RequestMapping(value = "/list", method = { RequestMethod.GET })
	@ResponseBody
	public Object list(User user) {
		APIModel model = new APIModel();
		List<User> list = userService.list(user);
		if (CollectionUtil.isNotEmpty(list)) {
			// 有用户数据的返回值
			model.set(0, "success", list);
		} else {
			// 没有用户数据的返回值
			model.set(1, Lang.msg("web.c.UserAPI.item0126"), list);
		}
		return model;
	}
}
